﻿using SlamCms.Common;

namespace System.Web.Mvc
{
	public static class HttpContextBaseExtensions
	{
		
		private const string UnknownIp = "0.0.0.0";

		public static bool IsSourceModified(this HttpContextBase context, string etag = null, DateTime? lastModified = null)
		{
			var request = context.Request;
			var response = context.Response;
			var dateModified = false;
			var eTagModified = false;
			
			// request values
			var requestETagHeader = request.Headers["If-None-Match"] ?? string.Empty;
			var requestIfModifiedSinceHeader = request.Headers["If-Modified-Since"] ?? string.Empty;
			DateTime requestIfModifiedSince;
			DateTime.TryParse(requestIfModifiedSinceHeader, out requestIfModifiedSince);

			// response values
			if (etag == null && HttpRuntime.UsingIntegratedPipeline) 
				etag = response.Headers["ETag"] ?? string.Empty;

			if (lastModified == null && HttpRuntime.UsingIntegratedPipeline)
			{
				var responseLastModifiedHeader = response.Headers["Last-Modified"] ?? string.Empty;
				DateTime parsedLastModified;
				if (DateTime.TryParse(responseLastModifiedHeader, out parsedLastModified))
					lastModified = parsedLastModified;
			}

			if (requestIfModifiedSince != DateTime.MinValue && lastModified.HasValue)
			{
				if (lastModified > requestIfModifiedSince)
				{
					TimeSpan diff = lastModified.Value - requestIfModifiedSince;
					if (diff > TimeSpan.FromSeconds(1))
					{
						dateModified = true;
					}
				}
			}
			else
				dateModified = true;

			//Leave the default for eTagModified = false so that if we
			//don't get an ETag from the server we will rely on the fileDateModified only
			if (string.IsNullOrEmpty(etag) == false)
				eTagModified = etag.Equals(requestETagHeader, StringComparison.Ordinal) == false;

			return (dateModified || eTagModified);
		}

		public static HttpResponseBase SetNotModified(this HttpResponseBase response)
		{
			response.SuppressContent = true;
			response.StatusCode = 304;
			response.StatusDescription = "Not Modified";
			response.AddHeader("Content-Length", "0");
			return response;
		}

		public static string GetRemoteAddress(this HttpRequestBase request)
		{
            var ip = request.ServerVariables["REMOTE_ADDR"]; // could be a proxy -- beware
            var ipForwarded = request.ServerVariables["HTTP_X_FORWARDED_FOR"];

            // check if we were forwarded from a proxy
            if (ipForwarded.HasValue())
            {
                ipForwarded = ipForwarded.ToIpAddress();
                if (ipForwarded.HasValue() && !ipForwarded.IsPrivateIp())
                    ip = ipForwarded;
            }

            return ip.HasValue() ? ip : UnknownIp;
        }
	}
}
